<!DOCTYPE html>
<html lang="zh-CN">
<head hexo-theme='https://github.com/volantis-x/hexo-theme-volantis/tree/4.1.5'>
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
    
  
  <!-- 渲染优化 -->
  <meta http-equiv='x-dns-prefetch-control' content='on' />
  <link rel='dns-prefetch' href='https://cdn.jsdelivr.net'>
  <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  <!-- 页面元数据 -->
  
  <title>论文阅读-Ekiden. A Platform for Confidentiality-Preserving, Trustworthy, and Performant Smart Contracts - Schenk - Blog</title>
  
    <meta name="keywords" content="sgx,blockchain">
  

  
    <meta name="description" content="论文Ekiden. A Platform for Confidentiality-Preserving, Trustworthy, and Performant Smart Contracts阅读笔记">
  

  <!-- feed -->
  

  <!-- import meta -->
  

  <!-- link -->
  
    <link rel="shortcut icon" type='image/x-icon' href="https://cdn.jsdelivr.net/gh/Schenk75/Source/logos/steroids.svg">
  

  <!-- import link -->
  

  
    
<link rel="stylesheet" href="/css/first.css">

  

  
  <link rel="stylesheet" href="/css/style.css" media="print" onload="this.media='all';this.onload=null">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
  

  <script id="loadcss"></script>

</head>

<body>
  

<header id="l_header" class="l_header auto shadow blur floatable show" style='opacity: 0' >
  <div class='container'>
  <div id='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h m-phone' id="pjax-header-nav-list">
        <li><a id="s-comment" class="fas fa-comments fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
          <li><a id="s-toc" class="s-toc fas fa-list fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
            <img no-lazy class='logo' src='https://cdn.jsdelivr.net/gh/Schenk75/Source@latest/logos/taiga.svg'/>
          
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h m-pc'>
          
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>

      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fas fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>

			<ul class='switcher nav-list-h m-phone'>
				
					<li><a class="s-search fas fa-search fa-fw" target="_self" href='javascript:void(0)'></a></li>
				
				<li>
          <a class="s-menu fas fa-bars fa-fw" target="_self" href='javascript:void(0)'></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>
		</div>
	</div>
  </div>
</header>

  <div id="l_body">
    <div id="l_cover">
  
    
        <div id="full" class='cover-wrapper post dock' style="display: none;">
          
            <div class='cover-bg lazyload placeholder' data-bg="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/interstellar.jpg"></div>
          
          <div class='cover-body'>
  <div class='top'>
    
    
      <p class="title">Schenk - Blog</p>
    
    
      <p class="subtitle">SJTUer | Cuber</p>
    
  </div>
  <div class='bottom'>
    <div class='menu navigation'>
      <div class='list-h'>
        
          
            <a href="/categories/"
              
              
              id="categories">
              <i class='fas fa-folder-open fa-fw'></i><p>分类</p>
            </a>
          
            <a href="/tags/"
              
              
              id="tags">
              <i class='fas fa-tags fa-fw'></i><p>标签</p>
            </a>
          
            <a href="/archives/"
              
              
              id="archives">
              <i class='fas fa-archive fa-fw'></i><p>归档</p>
            </a>
          
            <a href="/friends/"
              
              
              id="friends">
              <i class='fas fa-link fa-fw'></i><p>友链</p>
            </a>
          
            <a href="/about/"
              
              
              id="about">
              <i class='fas fa-info-circle fa-fw'></i><p>关于</p>
            </a>
          
        
      </div>
    </div>
  </div>
</div>

          <div id="scroll-down" style="display: none;"><i class="fa fa-chevron-down scroll-down-effects"></i></div>
        </div>
    
  
  </div>

    <div id='safearea'>
      <div class='body-wrapper' id="pjax-container">
        

<div class='l_main'>
  <article class="article post white-box reveal md shadow floatable article-type-post" id="post" itemscope itemprop="blogPost">
  


  
  <div class="article-meta" id="top">
    
    
    
      <h1 class="title">
        论文阅读-Ekiden. A Platform for Confidentiality-Preserving, Trustworthy, and Performant Smart Contracts
      </h1>
      <div class='new-meta-box'>
        
          
            
<div class='new-meta-item author'>
  <a class='author' href="/" rel="nofollow">
    <img no-lazy src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/avatar.jpg">
    <p>Schenk</p>
  </a>
</div>

          
        
          
            
  <div class='new-meta-item category'>
    <a class='notlink'>
      <i class="fas fa-folder-open fa-fw" aria-hidden="true"></i>
      <a class="category-link" href="/categories/Paper-Reading/">Paper Reading</a><span class="sep"></span><a class="category-link" href="/categories/SGX/">SGX</a>
    </a>
  </div>


          
        
          
            <div class="new-meta-item date" itemprop="dateUpdated" datetime="2022-07-20T11:49:41+08:00">
  <a class='notlink'>
    <i class="fas fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：2022年7月20日</p>
  </a>
</div>

          
        
          
            
  <div class="new-meta-item wordcount">
    <a class='notlink'>
      <i class="fas fa-keyboard fa-fw" aria-hidden="true"></i>
      <p>字数：7.3k字</p>
    </a>
  </div>
  <div class="new-meta-item readtime">
    <a class='notlink'>
      <i class="fas fa-hourglass-half fa-fw" aria-hidden="true"></i>
      <p>时长：27分钟</p>
    </a>
  </div>


          
        
          
            
  <div class="new-meta-item browse leancloud">
    <a class='notlink'>
      
      <div id="lc-pv" data-title="论文阅读-Ekiden. A Platform for Confidentiality-Preserving, Trustworthy, and Performant Smart Contracts" data-path="/2021/06/13/paper-reading/paper-Ekiden/">
        <i class="fas fa-eye fa-fw" aria-hidden="true"></i>
        <span id='number'><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span>
        次浏览
      </div>
    </a>
  </div>


          
        
      </div>
    
  </div>


  
  <h2 id="1-引入">1.引入</h2>
<p>现有的智能合约系统因此缺乏保密性和隐私性，它们不能安全地存储或计算敏感数据；区块链共识需求也使得智能合约在计算能力、存储容量和事务吞吐量方面的性能低下。</p>
<p>区块链和TEE有互补特性：</p>
<ul>
<li>区块链可以保证强可用性和持久性，而TEE不能保证可用性（因为宿主可以自行决定终止TEE），也不能可靠地访问网络或持久性存储</li>
<li>区块链的计算能力非常有限，必须公开其整个状态以供公共验证，而TEE与本地计算相比产生的开销很小，并通过远程认证提供具有机密性的可验证计算</li>
</ul>
<p>区块链和TEE结合会产生新的安全问题：由于TEE的基本限制是恶意主机可以任意操纵它的调度和I/O，TEE可能在任意时间中止，导致区块链上丢失和冲突的状态。TEE缺少可信时钟，因此很难更新到区块链的最新状态。可能存在的攻击例如针对区块链的完整性攻击危及TEE保护内容的机密性（如，攻击者可以通过提供一个伪造的区块链来绕过TEE强制执行的隐私计算，以退回到执行前并向其请求任意多个查询）</p>
<p>Ekiden采用计算与共识分离的架构。Ekiden在链下的TEE中使用计算节点执行私有数据的智能合约计算（避免了链上计算负担），然后验证它们在链上的正确执行，而区块链上的共识节点不需要使用TEE。Ekiden与共识机制无关，只需要一个能够验证来自计算节点的远程认证的区块链。</p>
<p>为了解决TEE的可用性和网络安全限制，Ekiden支持链上检查和合约状态存储。</p>
<h3 id="主要贡献">主要贡献</h3>
<ul>
<li>正式安全建模：使用一个理想的功能$F_{Ekiden}$来表达Ekiden的全部安全需求，在通用可组合性(UC)框架中概述安全性证明，表明Ekiden协议在并发组合下与$F_{Ekiden}$匹配；</li>
<li>TEE-区块链结合方案：系统地列举了区块链和TEE融合产生的基本缺陷，并提供了克服这些缺陷的通用技术；</li>
<li>性能：区块链可能是TEE-区块链混合系统的性能瓶颈。论文提供了优化，在不降低安全性的情况下最小化区块链的使用。</li>
</ul>
<h2 id="2-背景">2.背景</h2>
<h3 id="智能合约">智能合约</h3>
<p>智能合约系统的限制：</p>
<ul>
<li>对每个节点都完全复制的智能合约进行链上计算很昂贵</li>
<li>传统的智能合约系统不提供隐私保护，用户由假名区别，但是假名只提供很弱的隐私保护</li>
<li>合约状态和用户输入必须是公开的，以便矿工验证正确的计算，缺乏隐私</li>
</ul>
<h3 id="可信硬件">可信硬件</h3>
<ul>
<li>SGX生成的认证是不可伪造的</li>
<li>单单SGX不能保证可用性（恶意主机可以任意终止Enclave或丢弃消息）</li>
<li>SGX容易遭受侧信道攻击</li>
</ul>
<h2 id="3-TEE-区块链系统的技术挑战">3.TEE-区块链系统的技术挑战</h2>
<h3 id="容忍TEE故障">容忍TEE故障</h3>
<h4 id="可用性故障">可用性故障</h4>
<p>在SGX中，恶意主机可以终止Enclave，即使是诚实主机也可能在电源循环中丢失Enclave。TEE-区块链系统必须能够容忍这样的主机故障，确保崩溃的TEE可以延迟执行。</p>
<p>论文将TEE视为可消耗和可互换的，依赖区块链来解决并发性导致的任何冲突。为了确保任何特定的TEE很容易被替换，TEE是<strong>无状态的</strong>，并且任何持久状态都由区块链存储。</p>
<h4 id="侧信道">侧信道</h4>
<p>为了对付SGX的侧信道攻击，论文采用的方法是在空间和时间上进行划分，针对强敌手模型设计Ekiden中的关键组件，如密钥管理器，允许攻击者打破一小部分TEE的机密性，并限制其他组件对密钥管理器的访问。另外还采用了主动密钥旋转来限制泄漏密钥的权限。</p>
<h4 id="时钟故障">时钟故障</h4>
<p>SGX的时钟不可信，一个TEE-区块链混合协议必须尽量减少对TEE时钟的依赖。</p>
<p>在论文的设计中，不需要TEE拥有当前区块链的状态。具体来说，不需要TEE来区分陈旧状态和当前状态，而依赖于区块链主动拒绝任何陈旧输入状态的更新。</p>
<h3 id="PoW区块链的发布证明">PoW区块链的发布证明</h3>
<p>为了利用区块链作为持久存储，TEE必须能够有效地验证一个项目已经存储在区块链中，同时TEE也需要能够验证新块。这就需要一个可信时钟来防止敌手隔离Enclave而提供一个无效的子链。</p>
<p>论文利用了TEE的保密性，这样延迟时钟响应的攻击者就不能阻止Enclave成功验证区块链内容。</p>
<h3 id="TEE中的密钥管理">TEE中的密钥管理</h3>
<p>使用区块链持久化TEE状态的一个基本限制是缺乏保密性。通常可以通过在多个TEE中保存相同的密钥副本来实现密钥存储，虽然这种方法能很好地抵抗状态丢失，但是会造成更大的攻击面，在可用性和暴露风险之间需要权衡。</p>
<p>论文针对强敌手模型设计密钥管理器，允许攻击者打破一小部分TEE的机密性，并限制其他组件对密钥管理器的访问。</p>
<h3 id="执行结果的原子性交付">执行结果的原子性交付</h3>
<p>通常，对于有状态的TEE-区块链协议，TEE的执行产生两个消息：</p>
<ul>
<li>$m_1$：向调用者发送输出结果</li>
<li>$m_2$：向区块链发送状态更新</li>
</ul>
<p>这两个消息必须原子性交付，要么都交付成功，有一个交付失败则系统不可用：$m_1$ 在调用者收到时交付成功，$m_2$ 在区块链接受时交付成功，被拒绝的状态更新不是交付成功。</p>
<p>若不要求两个消息的原子性交付，可能产生的攻击有：</p>
<ul>
<li>如果只有 $m_1$ 被交付，可能会产生倒回攻击，由于TEE不能判断输入状态是否为新状态，因此攻击者可以提供旧状态以从旧状态恢复TEE的执行，直到获得想要的结果（公平性）；</li>
<li>如果只有 $m_2$ 被交付，用户可能永久丢失输出，因为一般不可能根据更新后的状态来重新产生相同的输出</li>
</ul>
<h2 id="4-Ekiden概述">4.Ekiden概述</h2>
<p>为了支持像信用评分这样的大规模隐私敏感应用程序，智能合约系统满足数据机密性保护以及高性能的同时要保持区块链提供的完整性和可用性。</p>
<h3 id="Ekiden概述">Ekiden概述</h3>
<p>Ekiden实现了用户自定义智能合约的安全执行环境，Ekiden合约是一个确定性的有状态程序。将合约程序的形式定义为 $(outp,st_{new}):=Contract(st_{old},inp)$ ，其中合约的输入是 $st_{old}$（前一个状态）和 $inp$（用户输入），生成输出 $outp$ 和新状态 $st_{new}$。</p>
<p>一旦部署在Ekiden上，智能合约就有了强大的保密性、完整性和可用性保证。在Ekiden中，有三种实体：</p>
<ul>
<li><strong>客户</strong>是智能合约的用户，在Ekiden中，客户可以通过秘密输入创建合同或执行现有的合同。无论哪种情况，客户机都将计算委托给计算节点；</li>
<li><strong>计算节点</strong>在合约TEE中执行合约并且生成用于证明状态更新正确性的证明，从而处理客户的请求。一组计算节点组成一个密钥管理委员会，并运行一个分布式协议来管理合约TEE使用的密钥，合约TEE通过密钥管理委员会来创建或恢复密钥；</li>
<li><strong>共识节点</strong>构成区块链，合约状态和认证都保存在这个区块链上。共识节点负责使用TEE检查状态更新的有效性。</li>
</ul>
<h3 id="工作流程">工作流程</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210609121506911.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210609121506911.png" srcset="" alt="image-20210609121506911"></p>
<p>简单起见，假设客户拥有使用的计算节点的优先级列表，客户记为 $P$ ，计算节点记为 $Comp$。</p>
<h4 id="合约创建">合约创建</h4>
<p>创建合约时，$P$ 将合约代码 $contract$ 发送给 $Comp$，$Comp$ 将 $Contract$ 加载到合约TEE中，合约TEE创建一个新鲜的合约id $cid$，从密钥管理委员会获取新鲜的 $(pk<sup>{in}_{cid},sk</sup>{in}<em>{cid})$ 对和 $k</em>{cid}^{state}$ 并生成加密的初始状态 $Enc(k^{state}<em>{cid},\vec{0})$ 和一个证明 $\sigma</em>{TEE}$（用于证明TEE初始化的正确性以及 $pk_{cid}^{in}$ 是对应于合约 $cid$ 的公钥）。</p>
<p>最后，$Comp$ 从认证服务获取 $\sigma_{TEE}$ 的正确性证明，该证明和 $\sigma_{TEE}$ 绑定到一个“certified”证明 $\pi$ 中。$Comp$ 接着发送 $(Contract,pk<sup>{in}_{cid},Enc(k</sup>{state}_{cid},\vec{0}),\pi)$ 到共识节点。</p>
<p>合约创建的完整协议由Fig2的 $Prot_{Ekiden}$ 中的 <em>create</em> 表示。</p>
<h4 id="请求执行">请求执行</h4>
<p>描述Fig1的过程：</p>
<p>(1) 为了使用输入 $inp$ 来执行合约 $cid$ ，$P$ 首先从区块链获取与合约 $cid$ 相关联的 $pk_{cid}^{in}$ ，计算 $inp_{ct}=Enc(pk^{in}<em>{cid},inp)$ ，并将消息 $(cid,inp</em>{ct})$ 发送给 $Comp$ 。如 $Prot_{Ekiden}$ 的Line8-11所示。</p>
<p>(2) $Comp$ 从区块链取出合约代码，以及合约 $cid$ 的加密过去状态 $st_{ct}=Enc(k^{state}<em>{cid},st</em>{old})$ ，并将 $st_{ct}$ 和 $inp_{ct}$ 加载到TEE中执行。 如 $Prot_{Ekiden}$ 的Line30-33所示。</p>
<p>(3-4) 合约TEE从密钥管理委员会获取 $k_{cid}^{state}$ 和 $sk^{in}<em>{cid}$ ，并使用它们解密 $st</em>{ct}$ 和 $inp_{ct}$ 。从而生成输出 $outp$ ，一个新的加密状态 $st<sup>{'}_{ct}=Enc(k_{cid}</sup>{state},st_{new})$ 和一个用于证明计算正确的签名 $\pi$ 。如 $Prot_{Ekiden}$ 的Line7-13所示。</p>
<p>(5a, 5b) 最后，$Comp$ 和 $P$ 执行一个原子交付协议，将 $outp$ 交付给 $P$ ，并将 $(st^{'}<em>{ct},\pi)$ 交付给共识节点。共识节点先验证 $\pi$ 再接受新状态 $st^{'}</em>{ct}$ 并将其存放在区块链上，只有在这之后，$P$ 才能接收到 $outp$ 。</p>
<p>Ekiden<strong>将请求执行与共识解耦</strong>。在以太坊中，请求执行被网络中的所有节点复制以达成共识，使得整个网络的速度和单个节点一样慢。而在Ekiden中，请求只被K个计算节点执行，K通常比较小，共识节点只需要验证K个正确执行的证明。</p>
<p>论文的实现中，<strong>使用签名 $\pi$ 来作为TEE正确执行的证明</strong>。一个计算节点 $Comp$ 通过如下方式获得签名 $\pi$ 。假设 $Comp$ 执行结果为一个输出 $st^{‘}<em>{ct}$ 和一个证明 $\sigma</em>{TEE}$（对合约代码和 $st^{’}<em>{ct}$ 的签名），$Comp$ 将 $\sigma</em>{TEE}$ 发送到IAS，IAS验证 $\sigma_{TEE}$ 并回复 $\pi=(b,\sigma_{TEE},\sigma_{IAS})$ ，其中 $b\in{0,1}$ 表明 $\sigma_{TEE}$ 的有效性，$\sigma_{IAS}$ 是IAS对 $b$ 和 $\sigma_{TEE}$ 的签名。然后 $\pi$ 被提交到共识节点作为 $st^{'}_{ct}$ 正确性的证明。</p>
<h3 id="Ekiden安全目标">Ekiden安全目标</h3>
<ul>
<li><strong>正确执行</strong>：合约状态转换反映了合约代码在给定状态和输入上的正确执行；</li>
<li><strong>一致性</strong>：在任何时候，区块链都存储与每个计算节点一致的单一状态转换序列；</li>
<li><strong>保密</strong>：Ekiden保证合约状态和来自诚实客户的输入对所有其他各方保密，另外Ekiden也能抵御一些密钥管理TEE的背叛；</li>
<li><strong>优雅的机密性降级</strong>：如果有计算节点违反机密性，Ekiden提供前向保密，并与受影响的TEE进行合理隔离。假设机密性违反发生在 $t$ ，攻击者最多能够获取 $t-\Delta$ 的历史。</li>
</ul>
<p>Ekiden不对合约级别的隐私泄露进行防御，如合约中的隐蔽信道、bug或侧信道。</p>
<h3 id="假设和威胁模型">假设和威胁模型</h3>
<h4 id="TEE">TEE</h4>
<p>假设SGX是正确实现和安全制造的，但由于SGX存在侧信道攻击，假设敌手可以危及一小部分TEE的机密性。</p>
<h4 id="区块链">区块链</h4>
<p>Ekiden对底层共识协议不可知。假设区块链正确执行规定的计算，并且总是可用的。Ekiden依赖共识节点来进行认证，进一步假设区块链提供发布证明，可以证明区块链上包含一些内容。</p>
<h4 id="威胁模型">威胁模型</h4>
<ul>
<li>系统中的各方都必须信任Ekiden和TEE</li>
<li>假设敌手可以控制除了一个计算节点之外的所有操作系统和网络堆栈，在受控节点上，敌手可以任意排序消息和调度进程</li>
<li>敌手可以操控任意数量的客户</li>
<li>客户不需要自己执行合约，也不需要可信硬件</li>
<li>诚实用户信任自己的代码和平台，但不相信其他客户</li>
<li>每个合约都有一个明确的策略来规定如何处理数据和服务请求</li>
<li>Ekiden不能防止合约有意或无意地通过软件漏洞泄露机密</li>
</ul>
<h2 id="5-Ekiden重要模块">5.Ekiden重要模块</h2>
<h3 id="发布证明">发布证明</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210609184625962.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210609184625962.png" srcset="" alt="image-20210609184625962"></p>
<p>为permissionless的区块链提出发布证明协议：</p>
<p>发布证明是一种在验证者 $\varepsilon$ 、合约TEE和不可信证明提供者 $P$ 之间的交互式证明。总的来说，只给 $P$ 有限的时间在足够困难的子链的块上发布消息，从而敌手很难伪造。</p>
<p>$\varepsilon$ 存储最近的一个checkpoint块 $CB$，可以通过 $CB$ 计算难度系数 $\delta(CB)$ ， $\varepsilon$ 向任何请求客户发出 $CB$ 版本，使客户能够验证 $CB$ 的新鲜度。给定一个有效的最近的 $CB$ ， $\varepsilon$ 可以通过 $\delta(CB)$ 来验证新的块。为了方便分析，论文中的难度系数是恒定的。</p>
<p>为了初始化 $m$ 的发布，$\varepsilon$ 获取时间戳 $t_1$ ， $\varepsilon$ 可能需要经过一段延时才能收到 $t_1$ 。收到 $t_1$ 之后，$\varepsilon$ 生成一个随机数 $r$ 并要求 $P$ 发布 $(m,r)$ 。$\varepsilon$ 收到 $P$ 发送的证明 $\pi_{(m,r)}$ 之后，获取时间戳 $t_2$ 。令 $n_c$ 为发布 $(m,r)$ 所需要的确认次数，$\tau$ 为期望的块间隔时间（区块链中的定值），$\epsilon$ 为一个乘法松弛因子，代表块产生的时间变化。例如，$\epsilon=1.5$ 表示 $\pi_{(m,r)}$ 的产生可以比预期在主链上的速度慢1.5倍。$\varepsilon$ 只有当 $t_2-t_1&lt;n_c\times\tau\times\epsilon$ 时才接受 $\pi_{(m,r)}$。</p>
<p>将 $\epsilon$ 设置为一个大的值可以降低错误拒绝的概率（拒绝诚实用户 $P$ 的证明会导致区块链增长速度减慢），然而大的 $\epsilon$ 值也会导致错误接受的概率增大。对于 $\epsilon&gt;1$ ，需要一个足够大的 $n_c$ 来使成功攻击的概率可忽略，然而大的 $n_c$ 意味着诚实用户 $P$ 需要等待很长时间才能获得输出，影响用户体验。</p>
<p>例如，假设攻击者有25%的算力，设置 $n_c=80$ 以及 $\epsilon=1.6$ 意味着攻击者需要预期2<sup>112</sup>次哈希才能伪造一个发布证明，而诚实的证明只有2<sup>-19</sup>的几率被拒绝。攻击者的伪造时间只有 $t_2-t_1$ ，而若 $\varepsilon$ 经过一段延时才收到 $t_1$ ，则 $t_2-t_1$ 就更短，对攻击者不利。</p>
<p>一旦一条消息在一个TEE中发布，其他TEE可以通过经认证的安全信道获取该消息及其证明，从而节省重复协议的成本。</p>
<h3 id="密钥管理">密钥管理</h3>
<p>每个Ekiden合约都和一系列密钥相关联，包括一个用于状态加密的对称密钥和用于加密客户输入的密钥对。</p>
<h4 id="敌手模型">敌手模型</h4>
<ul>
<li>假设敌手可以打破一定比例（$f%$）的TEE的机密性</li>
<li>假设参与主体有抵御女巫攻击的身份（交押金才能参与协议）</li>
<li>假设随时有足够多（$2f%$）的用户在线，从而密钥的可用性得到保证（通过经济奖惩来激励参与）</li>
</ul>
<h4 id="所需属性">所需属性</h4>
<p>由于解密密钥最终会暴露给合约TEE，而合约TEE本身也可能受到威胁，因此采用的密钥必须是短期的，来自暴露机会更低的的长期主密钥。密钥管理协议应满足的属性：</p>
<ul>
<li><strong>机密性</strong>：敌手无法窃取长期主密钥</li>
<li><strong>可用性</strong>：诚实的合约TEE能获取解密密钥</li>
<li><strong>前向保密</strong>：如果一个短期密钥被窃取，它不能用于解密早于 $t-\Delta$ 时间的加密消息</li>
</ul>
<h4 id="初步准备">初步准备</h4>
<ul>
<li>
<p><strong>分布式密钥生成（DKG）</strong>：DKG协议允许N个团体生成随机密钥，DKG协议允许的结果是一个秘密，通过秘密共享方案在各方之间共享；</p>
</li>
<li>
<p><strong>分布式伪随机函数（PRF）</strong>：PRF是函数 $F={f_s}<em>{s\in{S}}$ 的集合，并且对于随机索引 $s\leftarrow</em>$S$，$f_s(·)$ 于一个随机函数不能区分。</p>
<p>令 $G$ 是一个Schnorr group，$g$ 是一个生成器，$H:{0,1}^*\rightarrow G$ 是一个哈希函数，则 $f_s(x)=H(x)^s$ 是PRF族。</p>
<p>假设 $s$ 被多方采用 $(k,n)$-秘密分享方案分享，为了评估 $f_s(x)$ ，团体 $i$ 计算并输出 $y_i=H(x)^{s_i}$ ，在收集了至少 $k+1$ 的 ${y_i}$ 之后，可以通过多项式插值得到 $f_s(x)$：$f(x)=H(x)<sup>S=H(x)</sup>{\sum_{i\in A}{S_i\lambda_i}}=\prod_{i\in A}{y_i^{\lambda_i}}$ ，其中 $\lambda_i$ 是拉格朗日系数 $\lambda_i=\prod_{j\neq i}{\frac{-i}{i-j}}$ 。</p>
</li>
</ul>
<h4 id="协议">协议</h4>
<ul>
<li><strong>密钥管理委员会和长期密钥</strong>：对于抵抗女巫攻击的身份，可以抽取N 个节点来形成密钥管理委员会（KMC），其中N是系统参数。初始化一个合约 $c$ 时，KMC运行DKG协议来生成一个长期密钥 $k_c$ ，从而 $k_c$ 通过 $(\lceil fN\rceil,N)$-秘密分享方案在KMC成员之间秘密分享。</li>
<li><strong>生成短期密钥</strong>：假设短期密钥在每一轮都过期，为了在第 $t$ 轮获得合约 $c$ 的短期密钥，一个计算节点 $Comp$ 首先建立安全信道并与KMC成员认证身份。一旦验证了 $Comp$ 确实在执行 $c$ ，每个KMC成员 $i$ 计算 $k_{c,t,i}=H(t)<sup>{k_c</sup>i}$ ，并将 $k_{c,t,i}$ 发送给 $Comp$ 。在从 $A\subseteq$ KMC 收集了 $f+1$ 个结果之后，$Comp$ 可以生成第 $t$ 轮的短期密钥 $k_{c,t}=\prod_{i\in A}{k_{c,t,i}^{\lambda_i}}$ ，其中 $\lambda_i$ 是拉格朗日系数 。</li>
<li><strong>违规隔离</strong>：通过为每个计算节点强制执行隐私预算，主动隔离违反机密性的行为。为此，假设每个合约TEE有不可伪造的身份，密钥管理节点为每个计算节点 $Comp$ 维护一个计数器 $K_{Comp}$ 来记录请求次数。计数器会随着轮次增加而清零。只有当 $K_{Comp}&lt;K$ 时密钥管理节点才满足计算节点的请求，其中 $K$ 是一个系统参数。这样，无论一个被破坏的计算节点产生多少个TEE，它最多只能获得 $K$ 个密钥。</li>
</ul>
<h3 id="原子性交付">原子性交付</h3>
<p>假设TEE和调用客户 $P$ 之间有一个安全信道，通过以下协议实现 $m_1$ 和 $m_2$ 的原子交付：</p>
<ol>
<li>TEE从密钥管理器获取新鲜的密钥 $k$ ，并将加密的认证消息 $m_1^c=Enc(k,m_1)$ 发送给 $P$ ;</li>
<li>一旦 $P$ 确认收到 $m_1^c$ ，TEE将 $m_2$ 发送给区块链；</li>
<li>TEE得到 $m_2$ 的发布证明 $\pi_{m_2}$ 之后，将 $k$ 发送给 $P$。</li>
</ol>
<h2 id="6-协议细节和安全证明">6.协议细节和安全证明</h2>
<p>$Prot_{Ekiden}$ 的目的是实现一个通用可组合性(UC)理想功能 $F_{Ekiden}$ 。</p>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210609235608407.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210609235608407.png" srcset="" alt="image-20210609235608407"></p>
<h3 id="初步准备和符号说明">初步准备和符号说明</h3>
<h4 id="认证执行">认证执行</h4>
<p>使用 $G_{att}$ 正式定义可信硬件上经过验证的执行。一个party首先将程序 $prog$ 通过 <em>install</em> 消息加载进TEE中，通过 <em>resume</em> 调用，程序根据给定输入运行，生成输出 $outp$ 以及一个硬件密钥 $sk_{TEE}$ 下的签名认证 $\sigma_{TEE}=\sum_{TEE}.Sig(sk_{TEE},(prog,outp))$ ，其中 $sk_{TEE}$ 可以通过 $G_{att}.getpk()$ 获取。</p>
<p>如果一个TEE程序产生一对输出 $(outp_1,outp_2)$ ，认证只对 $outp_1$ 签名，即 $\sigma_{TEE}=\sum_{TEE}.Sig(sk_{TEE},(prog,outp_1))$ ，在 $outp_1$ 中包含 $outp_2$ 的哈希。</p>
<p>使用合约包装器来抽象例行常用功能，如状态加密，密钥管理等。被包装器扩充的合约 $c$ 称为 $\widehat{c}$ 。</p>
<h4 id="区块链-v2">区块链</h4>
<p>$F_{blockchain}[succ]$ 定义了区块链，参数 $succ$ 指定添加到存储中的新item的条件，对交易有效性的概念进行建模。</p>
<p>除了读写接口，$F_{blockchain}$ 提供了一个接口使得客户可以确定一个item是否包含在区块链内，这个接口避免了提前下载整个区块链。</p>
<h4 id="参数化-F-blockchain">参数化 $F_{blockchain}$</h4>
<p>在Ekiden中，存储的内容被解析为<strong>状态转换</strong>的有序数组，定义为 $trans_i=(H(st_{i-1}),st_i,\sigma_i)$ ，包含之前状态的哈希，新状态和对状态转换的正确性的TEE证明。存储可以被解释为一种特殊的初始状态，随后是一系列状态转换：$Storage=((Contract,st_0,\sigma_0),{trans_i}_{i\geq1})$ 。</p>
<p>状态转换必须扩展最新的状态，并且认证经过验证，它才是有效的。有效性验证是通过使用函数 $succ(·,·)$ 参数化 $F_{blockchain}$ 来实现的：当且仅当 $h=H(st_{old})$ 其中 $st_{old}$ 是 $Storage$ 中的最新状态，同时满足 $\sum_{TEE}.Vf(pk_{TEE},\sigma_{TEE},(h,st_{new}))$ 时，$succ(Storage,(h,st_{new},\sigma_{TEE}))=true$ 。这保证了状态转换链不会分叉。</p>
<h3 id="协议的正式规范">协议的正式规范</h3>
<p>$Prot_{Ekiden}$ 是Ekiden协议的正式规范，依赖 $G_{att}$ 和 $F_{blockchain}$ 作为认证执行和区块链的理想功能。$Prot_{Ekiden}$ 使用电子签名方案 $\sum(KGen,Sig,Vf)$ ，对称加密方案 $S\varepsilon(KGen,Enc,Dec)$ 以及非对称加密方案 $A\varepsilon(KGen,Enc,Dec)$。</p>
<h4 id="状态密钥分享">状态密钥分享</h4>
<p>每个合约都和一系列密钥绑定，合约TEE将管理密钥的工作委托给密钥管理TEE。在 $Prot_{Ekiden}$ 中，密钥管理的通信由 $keyManager$ 函数进行抽象。</p>
<h4 id="合约创建-v2">合约创建</h4>
<img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210613112729134.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210613112729134.png" srcset="" alt="image-20210613112729134" style="zoom:67%;" />
<p>创建Ekiden中的合约时，客户 $P_i$ 输入合约代码 $Contract$ ，并调用计算节点 $Comp$ 的 <code>create</code> 子程序。$Comp$ 将 $\widehat{Contract}$ 加载进TEE中，并调用 <em>create</em> 进行初始化。如Fig9所示，合约TEE创建一个新鲜的合约 $cid$ ，从密钥管理器获得新鲜的 $(pk_{cid}<sup>{in},sk</sup>{in}<em>{cid})$ 和 $k</em>{cid}^{state}$ ，并生成加密初始状态 $st_0$ 和一个证明 $\sigma_{TEE}$ ，$\sigma_{TEE}$ 证明了 $st_0$ 被正确初始化以及 $pk_{cid}^{in}$ 是合约 $cid$ 的对应公钥。计算节点 $Comp$ 将 $(Contract,cid,st_0,pk_{cid}^{in},\sigma_{TEE})$ 发送到 $F_{blockchain}$ 并等待回复。$Comp$ 将合约 $cid$ 返回给 $P_i$ ，然后 $P_i$ 验证合约 $cid$ 确实存储在 $F_{blockchain}$ 上。</p>
<h4 id="请求执行-v2">请求执行</h4>
<p>为了执行合约 $cid$ ，客户 $P_i$ 首先从 $F_{blockchain}$ 获得输入加密密钥 $pk_{cid}^{in}$ 。然后 $P_i$ 输入 $(cid,inp_{ct})$ 其中 $inp_{ct}$ 是经过 $pk^{in}<em>{cid}$ 加密和经过 $spk_i$ 认证的 $P_i$ 的输入，并调用 $Comp$ 的 <code>request</code> 子程序。$Comp$ 从 $F</em>{blockchain}$ 获取加密的之前状态 $st_{ct}$ ，并使用 $\widehat{Contract}$ 代码和输入 $(cid,inp_{ct},st_{ct})$ 启动一个合约TEE。</p>
<p>如Fig9所示，如果 $\sigma_{P_i}$ 验证通过，合约TEE使用从密钥管理器获得的密钥解密 $st_{ct}$ 和 $inp_{ct}$ ，并且执行合约 $Contract$ 得到结果 $(st_{new},outp)$ 。为了确保新状态和输出的原子性交付，$Comp$ 和 $P_i$ 执行第5章中描述的原子交付协议：</p>
<ul>
<li>首先合约TEE计算 $outp_{ct}=Enc(k^{out}<em>{cid},outp)$ 以及 $st</em>{ct}<sup>{'}=Enc(k</sup>{state}<em>{cid},st</em>{new})$ ，并且通过 $epk_i$ 建立的安全信道发送两个结果的认证给 $P_i$ ；</li>
<li>$P_i$ 通过调用 $Comp$ 的 <code>claim-output</code> 子程序来确认接收，该子程序使得合约TEE发送 $m_1=(st_{ct}^{'},outp_{ct},\sigma)$ 到 $F_{blockchain}$ 。$\sigma$ 保护 $m_1$ 的完整性，并以加密方式将新状态和输出绑定到以前的状态和输入，从而恶意的 $Comp$ 无法篡改它；</li>
<li>一旦 $m_1$ 被 $F_{blockchain}$ 接受，合约TEE通过安全信道将解密后的 $outp_{ct}$ 发送给 $P_i$ 。</li>
</ul>
<h3 id="Prot-Ekiden-的安全">$Prot_{Ekiden}$ 的安全</h3>
<p>定理1的证明在附录B</p>
<blockquote>
<p>定理1（$Prot_{Ekiden}$ 的安全性）：</p>
<p>假设 $G_{att}$ 的认证方案 $\sum_{TEE}$ 和数字签名 $\sum$ 在选择消息攻击（EU-CMA）下不可伪造，$H$ 是弱抗碰撞性的，$A\varepsilon$ 和 $S\varepsilon$ 是IND-CPA安全的。则 $Prot_{Ekiden}$ 在 $(G_{att}, F_{blockchain})$-结合模型中安全地实现了对静态敌手的 $F_{Ediden}$ 。</p>
</blockquote>
<h3 id="减轻应用程序级别泄露">减轻应用程序级别泄露</h3>
<p>Ekiden通过启用持久化的应用程序状态来减少应用程序级的隐私泄露（由于智能合约编写的问题导致的隐私泄露等）。</p>
<h2 id="7-实现">7.实现</h2>
<p>使用Rust SGX SDK实现了一个编译器，它可以自动将合约构建为可执行文件，并加载到计算节点中。</p>
<p>Ekiden与许多现有的区块链兼容。</p>
<h3 id="应用">应用</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210613142330692.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/paper-Ekiden/image-20210613142330692.png" srcset="" alt="image-20210613142330692"></p>
<h4 id="机器学习合约">机器学习合约</h4>
<p>为了演示对秘密数据的共享学习，论文实现了两个示例合约：</p>
<ul>
<li>基于财务记录的信用评分</li>
<li>根据医疗记录预测心脏病的可能性</li>
</ul>
<p>提供给这些示例合约的训练数据被视为敏感数据，不会在合约外作为明文公开。</p>
<h4 id="智能建筑热力学模型">智能建筑热力学模型</h4>
<p>论文移植了一个非线性最小二乘的实现，用于基于智能建筑提供的时间序列热力学数据来预测温度。Ekiden允许合约运行其模型，同时对传感器数据和模型保密，这表明Ekiden对高度交互的工作负载具有足够的响应能力。</p>
<h4 id="代币">代币</h4>
<p>最流行的以太坊合约是ERC20代币标准。论文实现了一个直接用Rust编写的代币合约，Ekiden会自动提供隐私和匿名性，而这是智能合约在以太坊主网上无法实现的。代币中每个用户的帐户余额是保密的。</p>
<h4 id="扑克">扑克</h4>
<p>论文实现了一个扑克合约，其中用户轮流向合约提交他们的行动，智能合约包含了洗牌和(有选择地)显示牌的所有游戏逻辑。扑克是区块链系统和安全多方计算的通用基准测试应用程序。Ekiden在每次行动后都将保存状态到区块链，并且可以从任何Enclave访问，所以如果玩家中止行动，秘密纸牌仍然能够被显示出来。</p>
<h4 id="加密猫">加密猫</h4>
<p>加密猫是一款以太坊游戏，允许用户繁殖虚拟猫，虚拟猫以ERC721代币的形式存储在链上。每只猫都有一组独特的基因，这些基因决定了它的外观和价值。后代的特征是由一个混合了父母基因的智能合约决定的。基因混合合约的源代码并不公开：游戏开发者的目标是让繁殖过程变得不可预测。</p>
<p>论文从以太坊区块链获取了基因混合合约的字节码，并使用Ekiden EVM端口执行。论文通过从以太坊网络复制真实交易来验证正确性。这个例子展示了Ekiden可以执行以太坊合约，即使源代码不可用。</p>
<p>加密猫的基因混合算法经过了逆向工程，这使得玩家能够优化自己繁殖出具有罕见特征的猫的机会，从而破坏游戏的生态系统。相比之下，Ekiden合约可以访问硬件中的随机性来源，并允许加密存储游戏算法。</p>
<h4 id="Origin">Origin</h4>
<p>Origin是一个在以太坊之上建立在线市场平台，论文移植了一个demo，允许用户使用Ether列出和购买道具。该应用进一步证明了以太坊的开发框架可以很容易地被Ekiden使用：在demo中使用的智能合约无需修改。基于Ekiden，区块链中的用户交易历史保持隐私，交易确认速度比以太坊更快。</p>
<h2 id="8-评估">8.评估</h2>
<p>与以太坊主网上的ERC20合约相比，Ekiden-BT可以支持吞吐量提高600倍、延迟降低400倍、货币成本降低1000倍的代币合约。虽然论文预计在使用更大规模区块链部署时，会出现一些轻微的性能下降，但性能优化显著降低了区块链速度的影响。</p>
<p>此外，论文证明Ekiden可以有效地支持计算密集型工作，如机器学习应用程序，这在以太坊上是成本高昂的。</p>
<h3 id="端到端延迟">端到端延迟</h3>
<h3 id="吞吐量">吞吐量</h3>
<h3 id="共识对吞吐量的影响">共识对吞吐量的影响</h3>
<p>to be continued</p>

  
  
    
    <div class='footer'>
      
      
      
      
    </div>
  
  
    


  <div class='article-meta' id="bottom">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date">
  <a class='notlink'>
    <i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i>
    <p>发布于：2021年6月13日</p>
  </a>
</div>

        
      
        
          
  
  <div class="new-meta-item meta-tags"><a class="tag" href="/tags/sgx/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>sgx</p></a></div> <div class="new-meta-item meta-tags"><a class="tag" href="/tags/blockchain/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>blockchain</p></a></div>


        
      
    </div>
  </div>


  
  

  
    <div class="prev-next">
      
        <a class='prev' href='/2021/06/13/paper-reading/paper-TZ4Fabric/'>
          <p class='title'><i class="fas fa-chevron-left" aria-hidden="true"></i>论文阅读-TZ4Fabric. Executing Smart Contracts with ARM TrustZone</p>
          <p class='content'>1.引入
Hyperledger  Fabric私有链码（FPC）是一个开源项目，它使通道上的节点（区块链网络中节点的子集）在TEE内执行智能合约，特别是在Intel  SGX Enclave内...</p>
        </a>
      
      
        <a class='next' href='/2021/06/06/paper-reading/paper-hawk/'>
          <p class='title'>论文阅读-Hawk.The Blockchain Model of Cryptography and Privacy-Preserving Smart Contracts<i class="fas fa-chevron-right" aria-hidden="true"></i></p>
          <p class='content'>1.引入
区块链上的可信时钟的存在对于协议中实现公平交易至关重要：恶意用户可能会过早地中止协议以避免资金支付，但是有了可信时钟，过早地中止协议会被判定为超时，这样区块链就可以将恶意用户的抵押存款...</p>
        </a>
      
    </div>
  
</article>


  

  






</div>
<aside class='l_side'>
  
  
    
    



  <section class="widget toc-wrapper shadow floatable desktop mobile" id="toc-div" >
    
  <header>
    
      <i class="fas fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E5%BC%95%E5%85%A5"><span class="toc-text">1.引入</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%BB%E8%A6%81%E8%B4%A1%E7%8C%AE"><span class="toc-text">主要贡献</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E8%83%8C%E6%99%AF"><span class="toc-text">2.背景</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6"><span class="toc-text">智能合约</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8F%AF%E4%BF%A1%E7%A1%AC%E4%BB%B6"><span class="toc-text">可信硬件</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-TEE-%E5%8C%BA%E5%9D%97%E9%93%BE%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%8A%80%E6%9C%AF%E6%8C%91%E6%88%98"><span class="toc-text">3.TEE-区块链系统的技术挑战</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%B9%E5%BF%8DTEE%E6%95%85%E9%9A%9C"><span class="toc-text">容忍TEE故障</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%AF%E7%94%A8%E6%80%A7%E6%95%85%E9%9A%9C"><span class="toc-text">可用性故障</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BE%A7%E4%BF%A1%E9%81%93"><span class="toc-text">侧信道</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%97%B6%E9%92%9F%E6%95%85%E9%9A%9C"><span class="toc-text">时钟故障</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#PoW%E5%8C%BA%E5%9D%97%E9%93%BE%E7%9A%84%E5%8F%91%E5%B8%83%E8%AF%81%E6%98%8E"><span class="toc-text">PoW区块链的发布证明</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#TEE%E4%B8%AD%E7%9A%84%E5%AF%86%E9%92%A5%E7%AE%A1%E7%90%86"><span class="toc-text">TEE中的密钥管理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C%E7%9A%84%E5%8E%9F%E5%AD%90%E6%80%A7%E4%BA%A4%E4%BB%98"><span class="toc-text">执行结果的原子性交付</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-Ekiden%E6%A6%82%E8%BF%B0"><span class="toc-text">4.Ekiden概述</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Ekiden%E6%A6%82%E8%BF%B0"><span class="toc-text">Ekiden概述</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B"><span class="toc-text">工作流程</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%88%E7%BA%A6%E5%88%9B%E5%BB%BA"><span class="toc-text">合约创建</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%AF%B7%E6%B1%82%E6%89%A7%E8%A1%8C"><span class="toc-text">请求执行</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Ekiden%E5%AE%89%E5%85%A8%E7%9B%AE%E6%A0%87"><span class="toc-text">Ekiden安全目标</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%81%87%E8%AE%BE%E5%92%8C%E5%A8%81%E8%83%81%E6%A8%A1%E5%9E%8B"><span class="toc-text">假设和威胁模型</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#TEE"><span class="toc-text">TEE</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8C%BA%E5%9D%97%E9%93%BE"><span class="toc-text">区块链</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%A8%81%E8%83%81%E6%A8%A1%E5%9E%8B"><span class="toc-text">威胁模型</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-Ekiden%E9%87%8D%E8%A6%81%E6%A8%A1%E5%9D%97"><span class="toc-text">5.Ekiden重要模块</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8F%91%E5%B8%83%E8%AF%81%E6%98%8E"><span class="toc-text">发布证明</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%86%E9%92%A5%E7%AE%A1%E7%90%86"><span class="toc-text">密钥管理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%95%8C%E6%89%8B%E6%A8%A1%E5%9E%8B"><span class="toc-text">敌手模型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%80%E9%9C%80%E5%B1%9E%E6%80%A7"><span class="toc-text">所需属性</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9D%E6%AD%A5%E5%87%86%E5%A4%87"><span class="toc-text">初步准备</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8D%8F%E8%AE%AE"><span class="toc-text">协议</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E5%AD%90%E6%80%A7%E4%BA%A4%E4%BB%98"><span class="toc-text">原子性交付</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-%E5%8D%8F%E8%AE%AE%E7%BB%86%E8%8A%82%E5%92%8C%E5%AE%89%E5%85%A8%E8%AF%81%E6%98%8E"><span class="toc-text">6.协议细节和安全证明</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9D%E6%AD%A5%E5%87%86%E5%A4%87%E5%92%8C%E7%AC%A6%E5%8F%B7%E8%AF%B4%E6%98%8E"><span class="toc-text">初步准备和符号说明</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%AE%A4%E8%AF%81%E6%89%A7%E8%A1%8C"><span class="toc-text">认证执行</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8C%BA%E5%9D%97%E9%93%BE-v2"><span class="toc-text">区块链</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%82%E6%95%B0%E5%8C%96-F-blockchain"><span class="toc-text">参数化 $F_{blockchain}$</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8D%8F%E8%AE%AE%E7%9A%84%E6%AD%A3%E5%BC%8F%E8%A7%84%E8%8C%83"><span class="toc-text">协议的正式规范</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%8A%B6%E6%80%81%E5%AF%86%E9%92%A5%E5%88%86%E4%BA%AB"><span class="toc-text">状态密钥分享</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%88%E7%BA%A6%E5%88%9B%E5%BB%BA-v2"><span class="toc-text">合约创建</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%AF%B7%E6%B1%82%E6%89%A7%E8%A1%8C-v2"><span class="toc-text">请求执行</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Prot-Ekiden-%E7%9A%84%E5%AE%89%E5%85%A8"><span class="toc-text">$Prot_{Ekiden}$ 的安全</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%87%8F%E8%BD%BB%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%BA%A7%E5%88%AB%E6%B3%84%E9%9C%B2"><span class="toc-text">减轻应用程序级别泄露</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7-%E5%AE%9E%E7%8E%B0"><span class="toc-text">7.实现</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BA%94%E7%94%A8"><span class="toc-text">应用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%90%88%E7%BA%A6"><span class="toc-text">机器学习合约</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%99%BA%E8%83%BD%E5%BB%BA%E7%AD%91%E7%83%AD%E5%8A%9B%E5%AD%A6%E6%A8%A1%E5%9E%8B"><span class="toc-text">智能建筑热力学模型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BB%A3%E5%B8%81"><span class="toc-text">代币</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%91%E5%85%8B"><span class="toc-text">扑克</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8A%A0%E5%AF%86%E7%8C%AB"><span class="toc-text">加密猫</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Origin"><span class="toc-text">Origin</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-%E8%AF%84%E4%BC%B0"><span class="toc-text">8.评估</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AB%AF%E5%88%B0%E7%AB%AF%E5%BB%B6%E8%BF%9F"><span class="toc-text">端到端延迟</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%9E%E5%90%90%E9%87%8F"><span class="toc-text">吞吐量</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%B1%E8%AF%86%E5%AF%B9%E5%90%9E%E5%90%90%E9%87%8F%E7%9A%84%E5%BD%B1%E5%93%8D"><span class="toc-text">共识对吞吐量的影响</span></a></li></ol></li></ol>
    </div>
  </section>


  


</aside>



        
        
          <!--此文件用来存放一些不方便取值的变量-->
<!--思路大概是将值藏到重加载的区域内-->

<script>
  window.pdata={}
  pdata.ispage=true;
  pdata.postTitle="论文阅读-Ekiden. A Platform for Confidentiality-Preserving, Trustworthy, and Performant Smart Contracts";
  pdata.commentPath="";
  pdata.commentPlaceholder="";

  var l_header=document.getElementById("l_header");
  
  l_header.classList.add("show");
  
</script>

        
      </div>
      
  
  <footer class="footer clearfix">
    <br><br>
    
      
        <div class='copyright'>
        <p><a target="_blank" rel="noopener" href="https://github.com/Schenk75/Schenk75.github.io">Copyright © 2020-2022 Schenk</a></p>

        </div>
      
    
  </footer>


      <a id="s-top" class="fas fa-arrow-up fa-fw" href='javascript:void(0)'></a>
    </div>
  </div>
  <div>
    <script>
window.volantis={};
window.volantis.loadcss=document.getElementById("loadcss");
/********************脚本懒加载函数********************************/
function loadScript(src, cb) {
var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
var script = document.createElement('script');
script.setAttribute('type','text/javascript');
if (cb) script.onload = cb;
script.setAttribute('src', src);
HEAD.appendChild(script);
}
//https://github.com/filamentgroup/loadCSS
var loadCSS = function( href, before, media, attributes ){
	var doc = window.document;
	var ss = doc.createElement( "link" );
	var ref;
	if( before ){
		ref = before;
	}
	else {
		var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes;
		ref = refs[ refs.length - 1];
	}
	var sheets = doc.styleSheets;
	if( attributes ){
		for( var attributeName in attributes ){
			if( attributes.hasOwnProperty( attributeName ) ){
				ss.setAttribute( attributeName, attributes[attributeName] );
			}
		}
	}
	ss.rel = "stylesheet";
	ss.href = href;
	ss.media = "only x";
	function ready( cb ){
		if( doc.body ){
			return cb();
		}
		setTimeout(function(){
			ready( cb );
		});
	}
	ready( function(){
		ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) );
	});
	var onloadcssdefined = function( cb ){
		var resolvedHref = ss.href;
		var i = sheets.length;
		while( i-- ){
			if( sheets[ i ].href === resolvedHref ){
				return cb();
			}
		}
		setTimeout(function() {
			onloadcssdefined( cb );
		});
	};
	function loadCB(){
		if( ss.addEventListener ){
			ss.removeEventListener( "load", loadCB );
		}
		ss.media = media || "all";
	}
	if( ss.addEventListener ){
		ss.addEventListener( "load", loadCB);
	}
	ss.onloadcssdefined = onloadcssdefined;
	onloadcssdefined( loadCB );
	return ss;
};
</script>
<script>
  
  loadCSS("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14/css/all.min.css", window.volantis.loadcss);
  
  
  
  
</script>
<!-- required -->

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script>

<script>
  function pjax_fancybox() {
    $(".md .gallery").find("img").each(function () { //渲染 fancybox
      var element = document.createElement("a"); // a 标签
      $(element).attr("class", "fancybox");
      $(element).attr("pjax-fancybox", "");  // 过滤 pjax
      $(element).attr("href", $(this).attr("src"));
      if ($(this).attr("data-original")) {
        $(element).attr("href", $(this).attr("data-original"));
      }
      $(element).attr("data-fancybox", "images");
      var caption = "";   // 描述信息
      if ($(this).attr('alt')) {  // 判断当前页面是否存在描述信息
        $(element).attr('data-caption', $(this).attr('alt'));
        caption = $(this).attr('alt');
      }
      var div = document.createElement("div");
      $(div).addClass("fancybox");
      $(this).wrap(div); // 最外层套 div ，其实主要作用还是 class 样式
      var span = document.createElement("span");
      $(span).addClass("image-caption");
      $(span).text(caption); // 加描述
      $(this).after(span);  // 再套一层描述
      $(this).wrap(element);  // 最后套 a 标签
    })
    $(".md .gallery").find("img").fancybox({
      selector: '[data-fancybox="images"]',
      hash: false,
      loop: false,
      closeClick: true,
      helpers: {
        overlay: {closeClick: true}
      },
      buttons: [
        "zoom",
        "close"
      ]
    });
  };
  function SCload_fancybox() {
    if ($(".md .gallery").find("img").length == 0) return;
    loadCSS("https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css", document.getElementById("loadcss"));
    setTimeout(function() {
      loadScript('https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js', pjax_fancybox)
    }, 1);
  };
  $(function () {
    SCload_fancybox();
  });
</script>


<!-- internal -->







  <script defer src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>




  
  
    <script>
      window.FPConfig = {
        delay: 0,
        ignoreKeywords: [],
        maxRPS: 5,
        hoverDelay: 25
      };
    </script>
    <script defer src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script>
  




  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
    var clipboard = new ClipboardJS('.btn-copy', {
        target: function (trigger) {
            return trigger.nextElementSibling
        }
    });
    function wait(callback, seconds) {
        var timelag = null;
        timelag = window.setTimeout(callback, seconds)
    }
    function pjax_initCopyCode() {
		if($(".highlight .code pre").length+$(".article pre code").length==0)return;
        var copyHtml = '';
        copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
        copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
        copyHtml += '</button>';
        $(".highlight .code pre").before(copyHtml);
        $(".article pre code").before(copyHtml);
        clipboard.off('success').on('success', function (e) {
            let $btn = $(e.trigger);
            $btn.addClass('copied');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-check-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPIED';
            wait(function () {
                $icon.removeClass('fa-check-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        });
        clipboard.off('error').on('error', function (e) {
            e.clearSelection();
            let $btn = $(e.trigger);
            $btn.addClass('copy-failed');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-times-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPY FAILED';
            wait(function () {
                $icon.removeClass('fa-times-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        })
    }
    $(function () {
        pjax_initCopyCode()
    });
</script>










  <script defer src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/tools/busuanzi.pure.mini.js" data-pjax></script>


  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/app.min.js"></script>




  
  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/search.min.js"></script>

  


<!-- optional -->

  <script>
const SearchServiceimagePath="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@master/img/";
const ROOT =  ("/" || "/").endsWith('/') ? ("/" || "/") : ("//" || "/" );
function listenSearch(){
  
    customSearch = new HexoSearch({
      imagePath: SearchServiceimagePath
    });
  
}
document.addEventListener("DOMContentLoaded", listenSearch);

</script>











  <script defer>

  const LCCounter = {
    app_id: 'u9j57bwJod4EDmXWdxrwuqQT-MdYXbMMI',
    app_key: 'jfHtEKVE24j0IVCGHbvuFClp',
    custom_api_server: '',

    // 查询存储的记录
    getRecord(Counter, url, title) {
      return new Promise(function (resolve, reject) {
        Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({url})))
          .then(resp => resp.json())
          .then(({results, code, error}) => {
            if (code === 401) {
              throw error;
            }
            if (results && results.length > 0) {
              var record = results[0];
              resolve(record);
            } else {
              Counter('post', '/classes/Counter', {url, title: title, times: 0})
                .then(resp => resp.json())
                .then((record, error) => {
                  if (error) {
                    throw error;
                  }
                  resolve(record);
                }).catch(error => {
                console.error('Failed to create', error);
                reject(error);
              });
            }
          }).catch((error) => {
          console.error('LeanCloud Counter Error:', error);
          reject(error);
        });
      })
    },

    // 发起自增请求
    increment(Counter, incrArr) {
      return new Promise(function (resolve, reject) {
        Counter('post', '/batch', {
          "requests": incrArr
        }).then((res) => {
          res = res.json();
          if (res.error) {
            throw res.error;
          }
          resolve(res);
        }).catch((error) => {
          console.error('Failed to save visitor count', error);
          reject(error);
        });
      });
    },

    // 构建自增请求体
    buildIncrement(objectId) {
      return {
        "method": "PUT",
        "path": `/1.1/classes/Counter/${ objectId }`,
        "body": {
          "times": {
            '__op': 'Increment',
            'amount': 1
          }
        }
      }
    },

    // 校验是否为有效的 UV
    validUV() {
      var key = 'LeanCloudUVTimestamp';
      var flag = localStorage.getItem(key);
      if (flag) {
        // 距离标记小于 24 小时则不计为 UV
        if (new Date().getTime() - parseInt(flag) <= 86400000) {
          return false;
        }
      }
      localStorage.setItem(key, new Date().getTime().toString());
      return true;
    },

    addCount(Counter) {
      var enableIncr = '' === 'true' && window.location.hostname !== 'localhost';
      enableIncr = true;
      var getterArr = [];
      var incrArr = [];
      // 请求 PV 并自增
      var pvCtn = document.querySelector('#lc-sv');
      if (pvCtn || enableIncr) {
        var pvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-sv', 'Visits').then((record) => {
          incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-sv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + 1;
              if (pvCtn) {
                pvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(pvGetter);
      }

      // 请求 UV 并自增
      var uvCtn = document.querySelector('#lc-uv');
      if (uvCtn || enableIncr) {
        var uvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-uv', 'Visitors').then((record) => {
          var vuv = this.validUV();
          vuv && incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-uv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + (vuv ? 1 : 0);
              if (uvCtn) {
                uvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(uvGetter);
      }

      // 请求文章的浏览数，如果是当前页面就自增
      var allPV = document.querySelectorAll('#lc-pv');
      if (allPV.length > 0 || enableIncr) {
        for (i = 0; i < allPV.length; i++) {
          let pv = allPV[i];
          let title = pv.getAttribute('data-title');
          var url = 'http://example.com' + pv.getAttribute('data-path');
          if (url) {
            var viewGetter = this.getRecord(Counter, url, title).then((record) => {
              // 是当前页面就自增
              let curPath = window.location.pathname;
              if (curPath.includes('index.html')) {
                curPath = curPath.substring(0, curPath.lastIndexOf('index.html'));
              }
              if (pv.getAttribute('data-path') == curPath) {
                incrArr.push(this.buildIncrement(record.objectId));
              }
              if (pv) {
                var ele = pv.querySelector('#lc-pv #number');
                if (ele) {
                  if (pv.getAttribute('data-path') == curPath) {
                    ele.innerText = (record.times || 0) + 1;
                  } else {
                    ele.innerText = record.times || 0;
                  }
                  pv.style.display = 'inline';
                }
              }
            });
            getterArr.push(viewGetter);
          }
        }
      }

      // 如果启动计数自增，批量发起自增请求
      if (enableIncr) {
        Promise.all(getterArr).then(() => {
          incrArr.length > 0 && this.increment(Counter, incrArr);
        })
      }

    },


    fetchData(api_server) {
      var Counter = (method, url, data) => {
        return fetch(`${ api_server }/1.1${ url }`, {
          method,
          headers: {
            'X-LC-Id': this.app_id,
            'X-LC-Key': this.app_key,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      this.addCount(Counter);
    },

    refreshCounter() {
      var api_server = this.app_id.slice(-9) !== '-MdYXbMMI' ? this.custom_api_server : `https://${ this.app_id.slice(0, 8).toLowerCase() }.api.lncldglobal.com`;
      if (api_server) {
        this.fetchData(api_server);
      } else {
        fetch('https://app-router.leancloud.cn/2/route?appId=' + this.app_id)
          .then(resp => resp.json())
          .then(({api_server}) => {
            this.fetchData('https://' + api_server);
          });
      }
    }

  };

  LCCounter.refreshCounter();

  document.addEventListener('pjax:complete', function () {
    LCCounter.refreshCounter();
  });
</script>








<script>
function listennSidebarTOC() {
  const navItems = document.querySelectorAll(".toc li");
  if (!navItems.length) return;
  const sections = [...navItems].map((element) => {
    const link = element.querySelector(".toc-link");
    const target = document.getElementById(
      decodeURI(link.getAttribute("href")).replace("#", "")
    );
    link.addEventListener("click", (event) => {
      event.preventDefault();
      window.scrollTo({
		top: target.offsetTop + 100,
		
		behavior: "smooth"
		
	  });
    });
    return target;
  });

  function activateNavByIndex(target) {
    if (target.classList.contains("active-current")) return;

    document.querySelectorAll(".toc .active").forEach((element) => {
      element.classList.remove("active", "active-current");
    });
    target.classList.add("active", "active-current");
    let parent = target.parentNode;
    while (!parent.matches(".toc")) {
      if (parent.matches("li")) parent.classList.add("active");
      parent = parent.parentNode;
    }
  }

  function findIndex(entries) {
    let index = 0;
    let entry = entries[index];
    if (entry.boundingClientRect.top > 0) {
      index = sections.indexOf(entry.target);
      return index === 0 ? 0 : index - 1;
    }
    for (; index < entries.length; index++) {
      if (entries[index].boundingClientRect.top <= 0) {
        entry = entries[index];
      } else {
        return sections.indexOf(entry.target);
      }
    }
    return sections.indexOf(entry.target);
  }

  function createIntersectionObserver(marginTop) {
    marginTop = Math.floor(marginTop + 10000);
    let intersectionObserver = new IntersectionObserver(
      (entries, observe) => {
        let scrollHeight = document.documentElement.scrollHeight + 100;
        if (scrollHeight > marginTop) {
          observe.disconnect();
          createIntersectionObserver(scrollHeight);
          return;
        }
        let index = findIndex(entries);
        activateNavByIndex(navItems[index]);
      },
      {
        rootMargin: marginTop + "px 0px -100% 0px",
        threshold: 0,
      }
    );
    sections.forEach((element) => {
      element && intersectionObserver.observe(element);
    });
  }
  createIntersectionObserver(document.documentElement.scrollHeight);
}

document.addEventListener("DOMContentLoaded", listennSidebarTOC);
document.addEventListener("pjax:success", listennSidebarTOC);
</script>

<!-- more -->




    
      


<script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script>


<script>
    var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',
        selectors: [
          "title",
          "#l_cover",
          "#pjax-container",
          "#pjax-header-nav-list"
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000
      });
    });

    document.addEventListener('pjax:send', function (e) {
      //window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      window.subData = null; // 移除标题（用于一二级导航栏切换处）
      if (typeof $.fancybox != "undefined") {
        $.fancybox.close();    // 关闭弹窗
      }
      volantis.$switcher.removeClass('active'); // 关闭移动端激活的搜索框
      volantis.$header.removeClass('z_search-open'); // 关闭移动端激活的搜索框
      volantis.$wrapper.removeClass('sub'); // 跳转页面时关闭二级导航

      // 解绑事件 避免重复监听
      volantis.$topBtn.unbind('click');
      $('.menu a').unbind('click');
      $(window).unbind('resize');
      $(window).unbind('scroll');
      $(document).unbind('scroll');
      $(document).unbind('click');
      $('body').unbind('click');
	  
    });

    document.addEventListener('pjax:complete', function () {
      // 关于百度统计对 SPA 页面的处理：
      // 方案一：百度统计>管理>单页应用设置中，打开开启按钮即可对SPA进行统计。 https://tongji.baidu.com/web/help/article?id=324
      // 方案二：取消注释下列代码。 https://tongji.baidu.com/web/help/article?id=235
      // 

      // 关于谷歌统计对 SPA 页面的处理：
      // 当应用以动态方式加载内容并更新地址栏中的网址时，也应该更新通过 gtag.js 存储的网页网址。
      // https://developers.google.cn/analytics/devguides/collection/gtagjs/single-page-applications?hl=zh-cn
      

      $('.nav-main').find('.list-v').not('.menu-phone').removeAttr("style",""); // 移除小尾巴的移除
      $('.menu-phone.list-v').removeAttr("style",""); // 移除小尾巴的移除
      $('script[data-pjax], .pjax-reload script').each(function () {
        $(this).parent().append($(this).remove());
      });
      try{
          if (typeof $.fancybox == "undefined") {
            SCload_fancybox();
          } else {
            pjax_fancybox();
          }
        
        
        
        
        
          pjax_initCopyCode();
        
        
        
        
        
      } catch (e) {
        console.log(e);
      }
	  
    });

    document.addEventListener('pjax:error', function (e) {
	  
      window.location.href = e.triggerElement.href;
    });
</script>

    
  </div>
</body>
</html>
